如何为OSS Java SDK配置访问凭证

重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

使用Java SDK发起OSS请求,您需要配置访问凭证。阿里云服务会通过访问凭证验证您的身份信息和访问权限。您可以根据使用场景对认证和授权的要求,选择不同的方式提供凭证。

注意事项

  • 如果您希望获取关于OSS支持的RegionEndpoint的对应关系,请参见OSS地域和访问域名

  • 如果您希望创建RAM用户的AccessKey,请参见创建AccessKey

  • 请您使用OSS Java SDK 3.17.4及以上版本以支持V4签名,详情请参见安装SDK

凭证提供者选型参考

OSS支持多种方式初始化凭证提供者,您可以根据使用场景对认证和授权的要求,选择对应的方式初始化凭证提供者。

凭证提供者初始化方式

适用场景

是否需要提供前置的AKSTS Token

底层实现基于的凭证

凭证有效期

凭证轮转或刷新方式

使用RAM用户的AK

部署运行在安全、稳定且不易受外部攻击的环境的应用程序,无需频繁轮转凭证就可以长期访问云服务

AK

长期

手动轮转

使用STS临时访问凭证

部署运行在不可信的环境的应用程序,希望能控制访问的有效期、权限

STS Token

临时

手动刷新

使用自动轮转的AK

部署运行在面临AK泄露风险的环境的应用程序,需要频繁轮转凭证才长期能访问云服务

AK

长期

自动轮转

使用RAMRoleARN

需要授权访问云服务,例如跨阿里云账号访问云服务的应用程序

STS Token

临时

自动刷新

使用ECSRAMRole

部署运行在阿里云的ECS实例、ECI实例、容器服务Kubernetes版的Worker节点中的应用程序

STS Token

临时

自动刷新

使用OIDCRoleARN

部署运行在阿里云的容器服务Kubernetes版的Worker节点中的不可信应用程序

STS Token

临时

自动刷新

使用函数计算上下文中的Credentials

部署运行在阿里云函数计算中的应用程序的函数

STS Token

临时

无需刷新

使用CredentialsURI

需要通过外部系统获取访问凭证的应用程序

STS Token

临时

自动刷新

使用自定义访问凭证

如果以上凭证配置方式都不满足要求时,您可以自定义获取凭证的方式

自定义

自定义

自定义

自定义

使用默认凭据链

当您在初始化凭据客户端不传入任何参数时,Credentials工具会使用默认凭据链方式初始化客户端。

自定义

自定义

自动刷新

常用配置示例

使用RAM用户的AK

如果您的应用程序部署运行在安全、稳定且不易受外部攻击的环境中,需要长期访问您的OSS,且不能频繁轮转凭证时,您可以使用阿里云主账号或RAM用户的AK(Access Key ID、Access Key Secret)初始化凭证提供者。需要注意的是,该方式需要您手动维护一个AK,存在安全性风险和维护复杂度增加的风险。

警告
  • 阿里云账号拥有资源的全部权限,AK一旦泄露,会给系统带来巨大风险,不建议使用。推荐使用最小化授权的RAM用户的AK。

  • 如需创建RAM用户的AK,请直接访问创建AccessKey。RAM用户的Access Key ID、Access Key Secret信息仅在创建时显示,请及时保存,如若遗忘请考虑创建新的AK进行轮换。

环境变量

  1. 使用RAM用户AccessKey配置环境变量。

    Linux
    1. 在命令行界面执行以下命令来将环境变量设置追加到~/.bashrc 文件中。

      echo "export OSS_ACCESS_KEY_ID='YOUR_ACCESS_KEY_ID'" >> ~/.bashrc
      echo "export OSS_ACCESS_KEY_SECRET='YOUR_ACCESS_KEY_SECRET'" >> ~/.bashrc
    2. 执行以下命令使变更生效。

      source ~/.bashrc
    3. 执行以下命令检查环境变量是否生效。

      echo $OSS_ACCESS_KEY_ID
      echo $OSS_ACCESS_KEY_SECRET
    macOS
    1. 在终端中执行以下命令,查看默认Shell类型。

      echo $SHELL
    2. 根据默认Shell类型进行操作。

      Zsh
      1. 执行以下命令来将环境变量设置追加到 ~/.zshrc 文件中。

        echo "export OSS_ACCESS_KEY_ID='YOUR_ACCESS_KEY_ID'" >> ~/.zshrc
        echo "export OSS_ACCESS_KEY_SECRET='YOUR_ACCESS_KEY_SECRET'" >> ~/.zshrc
      2. 执行以下命令使变更生效。

        source ~/.zshrc
      3. 执行以下命令检查环境变量是否生效。

        echo $OSS_ACCESS_KEY_ID
        echo $OSS_ACCESS_KEY_SECRET
      Bash
      1. 执行以下命令来将环境变量设置追加到 ~/.bash_profile 文件中。

        echo "export OSS_ACCESS_KEY_ID='YOUR_ACCESS_KEY_ID'" >> ~/.bash_profile
        echo "export OSS_ACCESS_KEY_SECRET='YOUR_ACCESS_KEY_SECRET'" >> ~/.bash_profile
      2. 执行以下命令使变更生效。

        source ~/.bash_profile
      3. 执行以下命令检查环境变量是否生效。

        echo $OSS_ACCESS_KEY_ID
        echo $OSS_ACCESS_KEY_SECRET
    Windows
    CMD
    1. CMD中运行以下命令。

      setx OSS_ACCESS_KEY_ID "YOUR_ACCESS_KEY_ID"
      setx OSS_ACCESS_KEY_SECRET "YOUR_ACCESS_KEY_SECRET"
    2. 运行以下命令,检查环境变量是否生效。

      echo %OSS_ACCESS_KEY_ID%
      echo %OSS_ACCESS_KEY_SECRET%
    PowerShell
    1. PowerShell中运行以下命令。

      [Environment]::SetEnvironmentVariable("OSS_ACCESS_KEY_ID", "YOUR_ACCESS_KEY_ID", [EnvironmentVariableTarget]::User)
      [Environment]::SetEnvironmentVariable("OSS_ACCESS_KEY_SECRET", "YOUR_ACCESS_KEY_SECRET", [EnvironmentVariableTarget]::User)
    2. 运行以下命令,检查环境变量是否生效。

      [Environment]::GetEnvironmentVariable("OSS_ACCESS_KEY_ID", [EnvironmentVariableTarget]::User)
      [Environment]::GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET", [EnvironmentVariableTarget]::User)
  2. 使用环境变量来传递凭证信息。

    import com.aliyun.oss.common.auth.CredentialsProviderFactory;
    import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
    
    public class AkDemoTest {
        public static void main(String[] args) throws Exception {
            // 从环境变量中获取凭证
            EnvironmentVariableCredentialsProvider credentialsProvider =  CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            // 使用credentialsProvider进行后续操作...
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);   
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
                    
            ossClient.shutdown();
        }
    }

静态凭证

您可以在代码中使用变量来引用凭证,这些变量在运行时会被环境变量、配置文件或其他外部数据源中的实际凭证值填充。

以下操作步骤以配置文件为例。

  1. 创建配置文件config.ini

    [credentials]
    alibaba_cloud_access_key_id = <ALIBABA_CLOUD_ACCESS_KEY_ID>
    alibaba_cloud_access_key_secret = <ALIBABA_CLOUD_ACCESS_KEY_SECRET>
  2. 使用配置文件来传递凭证信息。

    import com.aliyun.oss.common.auth.CredentialsProvider;
    import com.aliyun.oss.common.auth.DefaultCredentialProvider;
    import java.io.FileInputStream;
    import java.util.Properties;
    
    public class AkDemoTest {
        public static void main(String[] args) throws Exception {
            Properties properties = new Properties();
            // 设置config.ini文件路径
            String configFilePath = "config.ini";
    
            // 读取配置文件
            FileInputStream input = new FileInputStream(configFilePath);
            properties.load(input);
            input.close();
    
            // 从配置文件中获取AKSK
            String accessKeyId = properties.getProperty("alibaba_cloud_access_key_id");
            String accessKeySecret = properties.getProperty("alibaba_cloud_access_key_secret");
    
            CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
    
            // 使用credentialsProvider初始化客户端
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
    
            ossClient.shutdown();
    
        }
    }

使用STS临时访问凭证

如果您的应用程序需要临时访问OSS,您可以使用通过STS服务获取的临时身份凭证(Access Key ID、Access Key SecretSecurity Token)初始化凭证提供者。需要注意的是,该方式需要您手动维护一个STS Token,存在安全性风险和维护复杂度增加的风险。此外,如果您需要多次临时访问OSS,您需要手动刷新STS Token。

重要

环境变量

  1. 使用临时身份凭证设置环境变量。

    Mac OS X/Linux/Unix

    警告
    • 请注意,此处使用的是通过STS服务获取的临时身份凭证(Access Key ID、Access Key SecretSecurity Token),而非RAM用户的AK(Access Key ID、Access Key Secret)。

    • 请注意区分STS服务获取的Access Key IDSTS开头,例如“STS.L4aBSCSJVMuKg5U1****”。

    export OSS_ACCESS_KEY_ID=<STS_ACCESS_KEY_ID>
    export OSS_ACCESS_KEY_SECRET=<STS_ACCESS_KEY_SECRET>
    export OSS_SESSION_TOKEN=<STS_SECURITY_TOKEN>

    Windows

    警告
    • 请注意,此处使用的是通过STS服务获取的临时身份凭证(Access Key ID、Access Key SecretSecurity Token),而非RAM用户的AK(Access Key ID、Access Key Secret)。

    • 请注意区分STS服务获取的Access Key IDSTS开头,例如“STS.L4aBSCSJVMuKg5U1****”。

    set OSS_ACCESS_KEY_ID=<ALIBABA_CLOUD_ACCESS_KEY_ID>
    set OSS_ACCESS_KEY_SECRET=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
    set OSS_SESSION_TOKEN=<ALIBABA_CLOUD_SECURITY_TOKEN>
  2. 通过环境变量来传递凭证信息。

    import com.aliyun.oss.common.auth.CredentialsProviderFactory;
    import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
    
    public class StsDemoTest {
        public static void main(String[] args) throws Exception {
            // 从环境变量中获取凭证
            EnvironmentVariableCredentialsProvider credentialsProvider =  CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            
            // 使用credentialsProvider初始化客户端
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
    
            ossClient.shutdown();
        }
    }

静态凭证

您可以在应用程序中对凭据直接进行硬编码,显式设置要使用的临时访问密钥。

import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;

public class StsDemoTest {
    public static void main(String[] args) throws Exception {
        // 请设置为您通过STS服务获取的临时身份凭证Access Key ID、Access Key Secret和Security Token,而非RAM用户的身份凭证信息
        // 请注意区分STS服务获取的Access Key ID是以STS开头,如下所示
        String accessKeyId = "STS.NTZdStF79CVRTQuWCfXTT****"
        String accessKeySecret = "5rm8PfEiK8enp56zzAMX4RbZUraoKbWXvCf1xAuT****"
        String stsToken= "********"

        CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret, stsToken);

        // 使用credentialsProvider初始化客户端
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        // 显式声明使用 V4 签名算法
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
        // 创建OSSClient实例。
        OSS ossClient = OSSClientBuilder.create()
                .endpoint("endpoint")
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region("region")
                .build();

        ossClient.shutdown();
    }
}

更多场景化配置示例

使用自动轮转的AK

如果您的应用程序需要长期访问您的OSS,但部署运行的环境面临AK泄露的风险,需要频繁手动轮转(轮换)AK,您可以使用ClientKey初始化凭证提供者。该方式底层实现是AK。使用ClientKey后,密钥管理服务(KMS)可以对托管的RAM用户AK进行全自动的定期轮转,将静态的RAM用户AK动态化,从而降低AK泄漏的风险。除定期轮转外,KMS还支持立即轮转,在AK泄漏情况下快速更换AK。该方式无需您手动维护一个AK,从而降低安全性风险和维护复杂度增加的风险。如何获取ClientKey,请参见创建应用接入点

  1. 添加凭据客户端依赖。

    <!-- https://mvnrepository.com/artifact/com.aliyun/alibabacloud-secretsmanager-client -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>alibabacloud-secretsmanager-client</artifactId>
        <version>1.3.7</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-core -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-core</artifactId>
        <version>4.7.0</version>
    </dependency>
  2. 创建配置文件secretsmanager.properties

    # 访问凭据类型,固定为client_key
    credentials_type=client_key
    
    # 读取Client Key的解密密码:支持从环境变量或者文件读取,只需设置一种
    client_key_password_from_env_variable=<your client key private key password environment variable name>
    client_key_password_from_file_path=<your client key private key password file path>
    
    # Client Key的私钥文件路径
    client_key_private_key_path=<your client key private key file path>
    
    # 关联的KMS服务地域
    cache_client_region_id=[{"regionId":"<regionId>"}]
  3. 使用配置文件来传递凭证信息。

    import com.aliyun.oss.common.auth.Credentials;
    import com.aliyun.oss.common.auth.CredentialsProvider;
    import com.aliyun.oss.common.auth.DefaultCredentials;
    import com.aliyuncs.kms.secretsmanager.client.SecretCacheClient;
    import com.aliyuncs.kms.secretsmanager.client.SecretCacheClientBuilder;
    import com.aliyuncs.kms.secretsmanager.client.exception.CacheSecretException;
    import com.aliyuncs.kms.secretsmanager.client.model.SecretInfo;
    import org.codehaus.jettison.json.JSONException;
    import org.codehaus.jettison.json.JSONObject;
    
    public class ClientKeyDemoTest {
        public static void main(String[] args) throws CacheSecretException {
            final SecretCacheClient client = SecretCacheClientBuilder.newClient();
            CredentialsProvider credentialsProvider = new CredentialsProvider() {
                @Override
                public void setCredentials(Credentials credentials) {
                }
    
                @Override
                public Credentials getCredentials() {
                    try {
                        SecretInfo secretInfo = client.getSecretInfo("<secretName>");
                        JSONObject jsonObject = new JSONObject(secretInfo.getSecretValue());
    
                        String accessKeyId = jsonObject.getString("AccessKeyId");
                        String accessKeySecret = jsonObject.getString("AccessKeySecret");
    
                        return new DefaultCredentials(accessKeyId, accessKeySecret);
                    } catch (CacheSecretException | JSONException e) {
                        return null;
                    }
                }
            };
            // 使用credentialsProvider初始化客户端
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
    
            ossClient.shutdown();
        }
    }
    

使用RAMRoleARN

如果您的应用程序需要授权访问OSS,例如跨阿里云账号访问OSS,您可以使用RAMRoleARN初始化凭证提供者。该方式底层实现是STS Token。通过指定RAM角色的ARN(Alibabacloud Resource Name),Credentials工具会前往STS服务获取STS Token,并在会话到期前自动刷新STS Token。此外,您还可以通过为policy赋值来限制RAM角色到一个更小的权限集合。需要注意的是,该方式需要您提供一个AK,存在安全性风险和维护复杂度增加的风险。如何获取AK,请参见CreateAccessKey - 为RAM用户创建访问密钥。如何获取RAMRoleARN,请参见CreateRole - 创建角色

  1. 添加credentials依赖。

    <!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>credentials-java</artifactId>
        <version>LATEST</version>
    </dependency>
  2. 配置AKRAMRoleARN作为访问凭证。

    import com.aliyun.credentials.models.CredentialModel;
    import com.aliyun.oss.common.auth.Credentials;
    import com.aliyun.oss.common.auth.CredentialsProvider;
    import com.aliyun.oss.common.auth.DefaultCredentials;
    
    public class RamRoleArnAkDemoTest {
    
        public static void main(String[] args) {
    
            com.aliyun.credentials.models.Config config = new com.aliyun.credentials.models.Config();
            // 访问凭证类型。固定为ram_role_arn
            config.setType("ram_role_arn");
            // 要扮演的RAM角色ARN,示例值:acs:ram::123456789012****:role/adminrole,可以通过环境变量ALIBABA_CLOUD_ROLE_ARN设置RoleArn
            config.setRoleArn("<RoleArn>");
            // 从环境变量中获取AccessKeyId
            config.setAccessKeyId(System.getenv().get("ALIBABA_CLOUD_ACCESS_KEY_ID"));
            // 从环境变量中获取AccessKeySecret
            config.setAccessKeySecret(System.getenv().get("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
            // 角色会话名称,可以通过环境变量ALIBABA_CLOUD_ROLE_SESSION_NAME设置RoleSessionName
            config.setRoleName("<RoleSessionName>");
            // 设置更小的权限策略,非必填。示例值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
            config.setPolicy("<Policy>");
            // 设置角色会话有效期,非必填
            config.setRoleSessionExpiration(3600);
    
            final com.aliyun.credentials.Client credentialsClient = new com.aliyun.credentials.Client(config);
    
            CredentialsProvider credentialsProvider = new CredentialsProvider(){
                @Override
                public void setCredentials(Credentials credentials) {
                }
    
                @Override
                public Credentials getCredentials() {
                    CredentialModel credential = credentialsClient.getCredential();
                    return  new DefaultCredentials(credential.getAccessKeyId(), credential.getAccessKeySecret(), credential.getSecurityToken());
                }
            };
            // 使用credentialsProvider初始化客户端
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
    
            ossClient.shutdown();
        }
    }

使用ECSRAMRole

如果您的应用程序运行在ECS实例、ECI实例、容器服务KubernetesWorker节点中,建议您使用ECSRAMRole初始化凭证提供者。该方式底层实现是STS Token。ECSRAMRole允许您将一个角色关联到ECS实例、ECI实例或容器服务 Kubernetes 版Worker节点,实现在实例内部自动刷新STS Token。该方式无需您提供一个AKSTS Token,消除了手动维护AKSTS Token的风险。如何获取ECSRAMRole,请参见CreateRole - 创建角色。如何将一个角色关联到ECS实例,请参见实例RAM角色

  1. 添加credentials依赖。

    <!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>credentials-java</artifactId>
        <version>LATEST</version>
    </dependency>
  2. 配置ECSRAMRole作为访问凭证。

    import com.aliyun.credentials.models.CredentialModel;
    import com.aliyun.oss.common.auth.Credentials;
    import com.aliyun.oss.common.auth.CredentialsProvider;
    import com.aliyun.oss.common.auth.DefaultCredentials;
    
    public class EcsRamRoleDemoTest {
        public static void main(String[] args) {
    
            com.aliyun.credentials.models.Config config = new com.aliyun.credentials.models.Config();
            // 访问凭证类型。固定为ecs_ram_role。
            config.setType("ecs_ram_role");
            // 为ECS实例分配的RAM角色名称。
            config.setRoleName("<RoleName>");
    
            final com.aliyun.credentials.Client credentialsClient = new com.aliyun.credentials.Client(config);
    
            CredentialsProvider credentialsProvider = new CredentialsProvider(){
                @Override
                public void setCredentials(Credentials credentials) {
                }
    
                @Override
                public Credentials getCredentials() {
                    CredentialModel credential = credentialsClient.getCredential();
                    return  new DefaultCredentials(credential.getAccessKeyId(), credential.getAccessKeySecret(), credential.getSecurityToken());
                }
            };
            // 使用credentialsProvider初始化客户端
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
    
            ossClient.shutdown();
        }
    }

使用OIDCRoleARN

容器服务Kubernetes中设置了Worker节点RAM角色后,对应节点内的Pod中的应用也就可以像ECS上部署的应用一样,通过元数据服务(Meta Data Server)获取关联角色的STS Token。但如果容器集群上部署的是不可信的应用(比如部署您的客户提交的应用,代码也没有对您开放),您可能并不希望它们能通过元数据服务获取Worker节点关联实例RAM角色的STS Token。为了避免影响云上资源的安全,同时又能让这些不可信的应用安全地获取所需的STS Token,实现应用级别的权限最小化,您可以使用RRSA(RAM Roles for Service Account)功能。该方式底层实现是STS Token。阿里云容器集群会为不同的应用Pod创建和挂载相应的服务账户OIDC Token文件,并将相关配置信息注入到环境变量中,Credentials工具通过获取环境变量的配置信息,调用STS服务的AssumeRoleWithOIDC接口换取绑定角色的STS Token。该方式无需您提供一个AKSTS Token,消除了手动维护AKSTS Token的风险。详情请参见通过RRSA配置ServiceAccountRAM权限实现Pod权限隔离

  1. 添加credentials依赖。

    <!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>credentials-java</artifactId>
        <version>LATEST</version>
    </dependency>
  1. 配置OIDCRAM角色作为访问凭证。

    import com.aliyun.credentials.models.CredentialModel;
    import com.aliyun.oss.common.auth.Credentials;
    import com.aliyun.oss.common.auth.CredentialsProvider;
    import com.aliyun.oss.common.auth.DefaultCredentials;
    
    public class OidcRoleArnDemoTest {
        public static void main(String[] args) {
    
            com.aliyun.credentials.models.Config config = new com.aliyun.credentials.models.Config();
            // 指定Credential类型,固定值为oidc_role_arn
            config.setType("oidc_role_arn");
            // RAM角色名称ARN,可以通过环境变量ALIBABA_CLOUD_ROLE_ARN设置RoleArn
            config.setRoleArn("<RoleArn>");
            // OIDC提供商ARN,可以通过环境变量ALIBABA_CLOUD_OIDC_PROVIDER_ARN设置OidcProviderArn
            config.setOidcProviderArn("<OidcProviderArn>");
            // OIDC Token文件路径,可以通过环境变量ALIBABA_CLOUD_OIDC_TOKEN_FILE设置OidcTokenFilePath
            config.setOidcTokenFilePath("<OidcTokenFilePath>");
            // 角色会话名称,可以通过环境变量ALIBABA_CLOUD_ROLE_SESSION_NAME设置RoleSessionName
            config.setRoleSessionName("<RoleSessionName>");
            // 设置更小的权限策略,非必填。示例值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
            config.setPolicy("<Policy>");
            // 设置session过期时间
            config.setRoleSessionExpiration(3600);
    
            final com.aliyun.credentials.Client credentialsClient = new com.aliyun.credentials.Client(config);
    
            CredentialsProvider credentialsProvider = new CredentialsProvider(){
                @Override
                public void setCredentials(Credentials credentials) {
                }
    
                @Override
                public Credentials getCredentials() {
                    CredentialModel credential = credentialsClient.getCredential();
                    return  new DefaultCredentials(credential.getAccessKeyId(), credential.getAccessKeySecret(), credential.getSecurityToken());
                }
            };
            // 使用credentialsProvider初始化客户端
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
    
            ossClient.shutdown();
        }
    }

使用函数计算上下文中的Credentials

如果您的应用程序的函数部署运行在函数计算中,您可以使用函数计算上下文中的Credentials初始化凭证提供者。该方式底层实现是STS Token。函数计算根据函数配置的角色,通过扮演服务角色,而获取一个STS Token,然后通过上下文中的参数CredentialsSTS Token传递给您的应用程序。该STS Token的有效期为36小时,且不支持修改。函数的最大执行时间为24小时,因此,执行函数过程中,STS Token不会过期,您无需考虑刷新问题。该方式无需您提供一个AKSTS Token,消除了手动维护AKSTS Token的风险。如何授予函数计算访问OSS的权限,请参见授予函数计算访问其他云服务的权限

  1. 添加函数计算上下文依赖。

    <!-- https://mvnrepository.com/artifact/com.aliyun.fc.runtime/fc-java-core -->
    <dependency>
        <groupId>com.aliyun.fc.runtime</groupId>
        <artifactId>fc-java-core</artifactId>
        <version>1.4.1</version>
    </dependency>
  2. 使用函数计算上下文中的Credentials初始化凭证提供者。

    package example;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import com.aliyun.fc.runtime.Context;
    import com.aliyun.fc.runtime.Credentials;
    import com.aliyun.fc.runtime.StreamRequestHandler;
    import com.aliyun.oss.common.auth.CredentialsProvider;
    import com.aliyun.oss.common.auth.DefaultCredentialProvider;
    
    public class App implements StreamRequestHandler {
    
        @Override
        public void handleRequest(
            InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
    
            // 获取密钥信息,执行前,确保函数所在的服务配置了角色信息,并且角色需要拥有相关OSS权限,建议直接使用AliyunFCDefaultRole角色
            Credentials creds = context.getExecutionCredentials();
    
            // 使用获取到的凭证创建凭证提供者实例
            CredentialsProvider credentialsProvider = new DefaultCredentialProvider(creds.getAccessKeyId(), creds.getAccessKeySecret(), creds.getSecurityToken());
    
            // 使用credentialsProvider初始化客户端
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
    
            ossClient.shutdown();
    
            outputStream.write(new String("done").getBytes());
        }
    }

使用CredentialsURI

如果您的应用程序需要通过外部系统获取阿里云凭证,从而实现灵活的凭证管理和无密钥访问,您可以使用CredentialsURI初始化凭证提供者。该方式底层实现是STS Token。Credentials工具通过您提供的URI获取STS Token,完成凭证客户端初始化。该方式无需您提供一个AKSTS Token,消除了手动维护AKSTS Token的风险。

重要

请注意:

  • CredentialsURI指的是获取STS Token的服务器地址。

  • 提供CredentialsURI响应的后端服务需要实现STS Token的自动刷新逻辑,确保您的应用程序始终能获取到有效凭证。

  1. 为了使Credentials工具正确解析和使用STS Token,URI必须遵循以下响应协议:

    • 响应状态码:200

    • 响应体结构:

      {
          "Code": "Success",
          "AccessKeySecret": "AccessKeySecret",
          "AccessKeyId": "AccessKeyId",
          "Expiration": "2021-09-26T03:46:38Z",
          "SecurityToken": "SecurityToken"
      }
  2. 添加credentials依赖。

    <!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>credentials-java</artifactId>
        <version>LATEST</version>
    </dependency>
  3. 配置CredentialsURI作为访问凭证。

    import com.aliyun.credentials.models.CredentialModel;
    import com.aliyun.oss.common.auth.Credentials;
    import com.aliyun.oss.common.auth.CredentialsProvider;
    import com.aliyun.oss.common.auth.DefaultCredentials;
    
    public class CredentialsUriDemoTest {
        public static void main(String[] args) {
    
            com.aliyun.credentials.models.Config config = new com.aliyun.credentials.models.Config();
            // 访问凭证类型。固定为credentials_uri
            config.setType("credentials_uri");
            // 凭证的 URI,即您生成STS Token的服务器地址,格式为http://local_or_remote_uri/,可以通过环境变量ALIBABA_CLOUD_CREDENTIALS_URI设置CredentialsUri
            config.setCredentialsUri("<CredentialsUri>");
    
            final com.aliyun.credentials.Client credentialsClient = new com.aliyun.credentials.Client(config);
    
            CredentialsProvider credentialsProvider = new CredentialsProvider(){
                @Override
                public void setCredentials(Credentials credentials) {
                }
    
                @Override
                public Credentials getCredentials() {
                    CredentialModel credential = credentialsClient.getCredential();
                    return  new DefaultCredentials(credential.getAccessKeyId(), credential.getAccessKeySecret(), credential.getSecurityToken());
                }
            };
            // 使用credentialsProvider初始化客户端
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
    
            ossClient.shutdown();
        }
    }

使用自定义访问凭证

如果以上凭证配置方式都不满足要求时,您还可以通过实现Credential Providers接口的方式,来自定义凭证提供方式。需要注意,如果底层实现是STS Token,需要提供凭证的更新支持。

import com.aliyun.oss.common.auth.Credentials;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentials;

public class CustomCredentialProviderDemoTest {

    public static void main(String[] args) {

        CredentialsProvider credentialsProvider = new CredentialsProvider(){

            // 初始化变量
            String accessKeyId = null;
            // 初始化变量
            String accessKeySecrect = null;
            // 初始化变量
            // String token = null;

            @Override
            public void setCredentials(Credentials credentials) {
            }

            @Override
            public Credentials getCredentials() {
                //TODO
                //自定义访问凭证的获取方法

                // 返回长期凭证 access_key_id, access_key_secrect  
                return new DefaultCredentials(accessKeyId, accessKeySecrect);

                // 返回 临时凭证 access_key_id, access_key_secrect, token
                // 对于临时凭证,需要根据过期时间,刷新凭证。
                // return new DefaultCredentials(accessKeyId, accessKeySecrect, token);
            }
        };
        // 使用credentialsProvider初始化客户端
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        // 显式声明使用 V4 签名算法
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
        // 创建OSSClient实例。
        OSS ossClient = OSSClientBuilder.create()
                .endpoint("endpoint")
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region("region")
                .build();

        ossClient.shutdown();
    }
}

使用默认凭据链

当您在初始化凭据客户端不传入任何参数时,Credentials工具会使用默认凭据链方式初始化客户端。默认凭据的读取逻辑请参见默认凭据链

  1. 添加credentials依赖。

    <!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>credentials-java</artifactId>
        <version>LATEST</version>
    </dependency>
  2. 配置Credentials作为访问凭证。

    import com.aliyun.credentials.models.CredentialModel;
    import com.aliyun.oss.*;
    import com.aliyun.oss.common.auth.Credentials;
    import com.aliyun.oss.common.auth.CredentialsProvider;
    import com.aliyun.oss.common.auth.DefaultCredentials;
    
    public class Demo {
        public static void main(String[] args) {
            com.aliyun.credentials.Client credentialsClient = new com.aliyun.credentials.Client();
            CredentialsProvider credentialsProvider = new CredentialsProvider(){
                @Override
                public void setCredentials(Credentials credentials) {
                }
    
                @Override
                public Credentials getCredentials() {
                    CredentialModel credential = credentialsClient.getCredential();
                    return  new DefaultCredentials(credential.getAccessKeyId(), credential.getAccessKeySecret(), credential.getSecurityToken());
                }
            };
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);  
            // 使用credentialsProvider初始化客户端
            // 创建OSSClient实例。
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint("endpoint")
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region("region")
                    .build();
            ossClient.shutdown();
        }
    }

常见问题

在使用通过STS服务获取的临时身份凭证去初始化凭证提供者时,误使用RAM用户的AK

当您使用通过STS服务获取的临时身份凭证(Access Key ID、Access Key SecretSecurity Token)初始化访问凭证时,请勿混淆STS服务返回的AKRAM用户的AK,STS对应的AK是以STS开头,示例如下:

image

如何查看RAM用户的AK?是否可以查看旧的AccessKey Secret?

  1. 如需查看RAM用户的AK,请直接参考文档查看RAM用户的AccessKey信息

  2. RAM用户的AccessKey Secret仅在创建时显示,之后无法查看,若已经遗忘了的话无法找回。您可以直接访问RAM控制台选择具体用户,并创建新的AccessKey进行轮换。详细请参见创建AccessKey

在使用外网Endpoint访问OSS时,报错无法连接该如何排查?

出现外网Endpoint无法连接的问题,通常是因为使用了错误的Endpoint地址或Bucket所在地域与请求的Endpoint不匹配。请您按照以下步骤检查:

  1. 确认Bucket所在地域:登录阿里云控制台,找到您的Bucket,确认其所在地域。

  2. 使用正确的Endpoint:根据Bucket所在地域,使用对应的外网Endpoint。例如,如果Bucket位于华东1(杭州),则应使用oss-cn-hangzhou.aliyuncs.com。各地域的Endpoint信息请参见OSS地域和访问域名

  3. 检查网络连接:确保您的网络环境可以正常访问互联网,避免因网络问题导致连接失败。

如果遇到报错问题该如何查询具体的错误类型?

关于错误类型的查询,OSS文档提供了EC错误码供您参阅,例如关于认证方面的常见报错问题,可参见02-AUTH